package com.tools.scanner.ad

import android.app.Activity
import android.util.ArrayMap
import android.util.Log
import android.view.View
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.OnceLiveData
import com.google.android.gms.ads.AdView
import com.tools.scanner.ad.callback.OnAdLoadCallback
import com.tools.scanner.ad.callback.OnAdShowCallback
import com.tools.scanner.ad.impl.BannerAdImpl
import com.tools.scanner.ad.impl.BaseAdImpl
import com.tools.scanner.ad.impl.InterstitialAdImpl
import com.tools.scanner.ad.impl.NativeAdImpl
import com.tools.scanner.bean.AdInfo
import com.tools.scanner.utils.LogUtil
import com.tools.scanner.utils.PreferencesUtil
import com.tools.scanner.viewmodel.DataViewModel

object AdManager {

    data class AdLoadResult(
        val adLocation: String,
        val status: AdLoadStatus,
        val isNoFill: Boolean = false
    )

    enum class AdLoadStatus {
        LOADING,
        SUCCESS,
        FAIL,
        NO_CONFIG
    }

    data class AdShowResult(val adLocation: String, val status: AdShowStatus)

    enum class AdShowStatus {
        CLICK,
        DISMISSED,
        SHOW
    }

    private val mLoadAdBuffer = ArrayMap<String, BaseAdImpl>()

    private val mAdLoadStatusLiveDataBuffer = ArrayMap<String, MutableLiveData<AdLoadResult>>()
    private val mAdShowStatusLiveDataBuffer = ArrayMap<String, MutableLiveData<AdShowResult>>()

    fun isLoadComplete(adLocation: String): Boolean {
        return mLoadAdBuffer[adLocation]?.isAdAvailable() ?: false
    }

    fun getAdInfo(location: String): AdInfo? {
        DataViewModel.getAdInfoList()?.forEach {
            if (it.adLocation == location) {
                return it
            }
        }
        return null
    }

    fun loadBannerAd(adView: AdView, adLocation: String) {
        val liveData = getAdLoadStatusLiveData(adLocation)

        val adId = getAdId(adLocation)
        if (adId == null) {
            liveData.value = AdLoadResult(adLocation, AdLoadStatus.NO_CONFIG)
            return
        }

        var adImpl = mLoadAdBuffer[adLocation]
        if (adImpl == null) {
            adImpl = BannerAdImpl(adId, adLocation)
            mLoadAdBuffer[adLocation] = adImpl
        }

        adImpl.setAdLoadListener(object : OnAdLoadCallback {
            override fun onAdLoading(adLocation: String) {
                liveData.value = AdLoadResult(adLocation, AdLoadStatus.LOADING)
            }

            override fun onAdComplete(adLocation: String, state: Boolean, isNoFill: Boolean) {
                if (state) {
                    liveData.value = AdLoadResult(adLocation, AdLoadStatus.SUCCESS)
                } else {
                    liveData.value = AdLoadResult(adLocation, AdLoadStatus.FAIL, isNoFill)
                }
            }
        })

        adImpl.startLoad(adView)
    }

    fun getBannerAdView() {

    }

    fun loadInterstitialAd(adLocation: String) {
        val liveData = getAdLoadStatusLiveData(adLocation)

        val adId = getAdId(adLocation)
        if (adId == null) {
            liveData.value = AdLoadResult(adLocation, AdLoadStatus.NO_CONFIG)
            return
        }

        var adImpl = mLoadAdBuffer[adLocation]
        if (adImpl == null) {
            adImpl = InterstitialAdImpl(adId, adLocation)
            mLoadAdBuffer[adLocation] = adImpl
        }

        adImpl.setAdLoadListener(object : OnAdLoadCallback {
            override fun onAdLoading(adLocation: String) {
                liveData.value = AdLoadResult(adLocation, AdLoadStatus.LOADING)
            }

            override fun onAdComplete(adLocation: String, state: Boolean, isNoFill: Boolean) {
                if (state) {
                    liveData.value = AdLoadResult(adLocation, AdLoadStatus.SUCCESS)
                } else {
                    liveData.value = AdLoadResult(adLocation, AdLoadStatus.FAIL, isNoFill)
                }
            }
        })

        adImpl.startLoad()
    }

    fun showInterstitialAd(adLocation: String, activity: Activity) {
        val adImpl = mLoadAdBuffer[adLocation]
        if (adImpl == null) {
            LogUtil.logE("interstitialAd is null，adLocation：$adLocation");
            return
        }

        val liveData = getAdShowStatusLiveData(adLocation)

        adImpl.setAdShowListener(object : OnAdShowCallback {
            override fun onAdClicked(adLocation: String) {
                liveData.value = AdShowResult(adLocation, AdShowStatus.CLICK)
            }

            override fun onAdDismissed(adLocation: String) {
                liveData.value = AdShowResult(adLocation, AdShowStatus.DISMISSED)
            }

            override fun onAdShow(adLocation: String) {
                clearStepCount(adLocation)
                liveData.value = AdShowResult(adLocation, AdShowStatus.SHOW)
            }

            override fun onAdShowFail(adLocation: String, msg: String) {
                liveData.value = AdShowResult(adLocation, AdShowStatus.DISMISSED)
            }

        })
        adImpl.show(activity)
    }

    fun loadNativeAd(adLocation: String) {
        val liveData = getAdLoadStatusLiveData(adLocation)

        val adId = getAdId(adLocation)
        if (adId == null) {
            liveData.value = AdLoadResult(adLocation, AdLoadStatus.NO_CONFIG)
            return
        }

        var adImpl = mLoadAdBuffer[adLocation]
        if (adImpl == null) {
            adImpl = NativeAdImpl(adId, adLocation)
            mLoadAdBuffer[adLocation] = adImpl
        }

        adImpl.setAdLoadListener(object : OnAdLoadCallback {
            override fun onAdLoading(adLocation: String) {
                liveData.value = AdLoadResult(adLocation, AdLoadStatus.LOADING)
            }

            override fun onAdComplete(adLocation: String, state: Boolean, isNoFill: Boolean) {
                Log.e("yangyangyang", "onAdCompleteonAdComplete")
                if (state) {
                    liveData.value = AdLoadResult(adLocation, AdLoadStatus.SUCCESS)
                } else {
                    liveData.value = AdLoadResult(adLocation, AdLoadStatus.FAIL, isNoFill)
                }
            }

        })
        adImpl.startLoad()
    }

    fun getNativeAdView(adLocation: String): View? {
        val adImpl = mLoadAdBuffer[adLocation]
        if (adImpl == null) {
            LogUtil.logE("nativeAd is null，adLocation：$adLocation");
            return null
        }

        val liveData = getAdShowStatusLiveData(adLocation)

        adImpl.setAdShowListener(object : OnAdShowCallback {
            override fun onAdClicked(adLocation: String) {
                liveData.value = AdShowResult(adLocation, AdShowStatus.CLICK)
            }

            override fun onAdDismissed(adLocation: String) {
                liveData.value = AdShowResult(adLocation, AdShowStatus.DISMISSED)
            }

            override fun onAdShow(adLocation: String) {
                clearStepCount(adLocation)
                liveData.value = AdShowResult(adLocation, AdShowStatus.SHOW)
            }

            override fun onAdShowFail(adLocation: String, msg: String) {
                liveData.value = AdShowResult(adLocation, AdShowStatus.DISMISSED)
            }

        })
        return adImpl.getNativeView()
    }

    fun getAdId(adLocation: String): String? {
        val adInfo: AdInfo = getAdInfo(adLocation) ?: return null
        if (!adInfo.isShow) {
            return null
        }

        val count = getStepCount(adLocation)
        if (count < adInfo.step) {
            return null
        }

        return adInfo.adId
    }

    fun subscribeAdLoadStatusEvent(
        adLocation: String,
        owner: LifecycleOwner,
        observer: Observer<AdLoadResult>
    ) {
        getAdLoadStatusLiveData(adLocation).observe(owner, observer)
    }

    private fun getAdLoadStatusLiveData(adLocation: String): MutableLiveData<AdLoadResult> {
        var liveData = mAdLoadStatusLiveDataBuffer[adLocation]
        if (liveData == null) {
            liveData = OnceLiveData<AdLoadResult>()
            mAdLoadStatusLiveDataBuffer[adLocation] = liveData
        }
        return liveData
    }

    fun subscribeAdShowStatusEvent(
        adLocation: String,
        owner: LifecycleOwner,
        observer: Observer<AdShowResult>
    ) {
        getAdShowStatusLiveData(adLocation).observe(owner, observer)
    }

    private fun getAdShowStatusLiveData(adLocation: String): MutableLiveData<AdShowResult> {
        var liveData = mAdShowStatusLiveDataBuffer[adLocation]
        if (liveData == null) {
            liveData = OnceLiveData<AdShowResult>()
            mAdShowStatusLiveDataBuffer[adLocation] = liveData
        }
        return liveData
    }

    fun getStepCount(adLocation: String): Int {
        val key = getStepKey(adLocation)
        val count = PreferencesUtil.getIntValue(key, 0)
        return count
    }

    fun addStepCount(adLocation: String) {
        var count = getStepCount(adLocation)
        count++

        val key = getStepKey(adLocation)
        PreferencesUtil.putValue(key, count)
    }

    private fun clearStepCount(adLocation: String) {
        val key = getStepKey(adLocation)
        PreferencesUtil.putValue(key, 0)
    }

    private fun getStepKey(adLocation: String): String {
        return "${adLocation}_step"
    }
}